﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Web;
using System.IO;
using Medianamik.Core.Interfaces;

namespace Medianamik.Core.Resources
{
    public class MedianamikAssembly : IMedianamikAssembly
    {
        #region .ctor

        public MedianamikAssembly(string pVirtualPath, string pFileName, byte pDepth)
        {
            AppRelativeVirtualPath = VirtualPathUtility.ToAppRelative(pVirtualPath);
            FileName = pFileName;
            Depth = pDepth;
        }

        #endregion 

        public virtual string AppRelativeVirtualPath
        {
            get;
            private set;
        }

        public virtual string FileName
        {
            get;
            private set;
        }

        public virtual byte Depth
        { get; private set; }

        public virtual bool IsPathVirtual(string pPath)
        {
            string checkPath = VirtualPathUtility.ToAppRelative(pPath);
            return checkPath.StartsWith(this.AppRelativeVirtualPath, StringComparison.InvariantCultureIgnoreCase);
        }

        private Assembly _assembly;
        public Assembly GetAssembly()
        {
            var binDirectory = HttpRuntime.BinDirectory;
            return _assembly
                ?? (_assembly = Assembly.LoadFile(Path.Combine(binDirectory, FileName)));
        }

        private string[] _resourceNames;
        public string[] GetAssemblyResourceNames()
        {
            if (_resourceNames == null)
            {
                var assembly = GetAssembly();
                var assemblyName = assembly.GetName().Name;
                _resourceNames = assembly.GetManifestResourceNames()
                    .Select(mrn => mrn.Substring(assemblyName.Length, mrn.Length - assemblyName.Length).TrimStart('.'))
                    .ToArray();
            }
            return _resourceNames;
        }

        public bool TryGetAssemblyResourceName(string pVirtualPath, out string pResourceName)
        {
            var checkPath = VirtualPathUtility.ToAppRelative(pVirtualPath);
            var checkName = checkPath.Substring(this.AppRelativeVirtualPath.Length, checkPath.Length - this.AppRelativeVirtualPath.Length).TrimStart('/').Replace('/', '.');
            pResourceName = this.GetAssemblyResourceNames()
                .FirstOrDefault(mrn => string.Equals(mrn, checkName, StringComparison.InvariantCultureIgnoreCase));

            return pResourceName != null;
        }
              

        private ResourceInfo[] _resourceInfos;
        public ResourceInfo[] GetResourceInfos()
        {
            var assembly = GetAssembly();
            if (_resourceInfos == null)
            {
                _resourceInfos = GetAssemblyResourceNames().Select(arn => new ResourceInfo(GetPathFromResourceName(arn), arn, assembly)).ToArray();
            }
            return _resourceInfos;
        }
        
        private string GetPathFromResourceName(string pResourceName)
        {
            var tokens = pResourceName.Split('.');

            // le LastToken est considéré comme l'extension du fichier
            // le fichier devrait donc toujours en avoir un
            var extension = tokens.Last();

            // Le reste des tokens constitue le path+filename
            var filename = tokens.Take(tokens.Length -1).ToArray();

            return VirtualPathUtility.AppendTrailingSlash(this.AppRelativeVirtualPath) + string.Join("/", filename) + '.' + extension; 
        }


    }
}
